package info.niwota.web.bt;

import info.niwota.web.Debug;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;

public class RemoteDeviceDiscovery {

	public static final List<RemoteDevice> devices = new ArrayList<RemoteDevice>();

	public static List<RemoteDevice> getDevices(boolean refresh) throws Exception {
		if (refresh) {
			find();
		}
		return devices;
	}
	
	public static RemoteDevice retrieve(String address) throws Exception {
		if (Debug.DEBUG) {
			System.out.println("retrive : " + address);
		}
		DiscoveryAgent agent = LocalDevice.getLocalDevice().getDiscoveryAgent();
		
		RemoteDevice[] devices = agent.retrieveDevices(DiscoveryAgent.CACHED);  
		if (devices != null && devices.length > 0) {
			for (RemoteDevice d: devices) {
				if (Debug.DEBUG) {
					System.out.println("cached: " + d.getBluetoothAddress());
				}
				if (d.getBluetoothAddress().equalsIgnoreCase(address)) {
					return d;
				}
			}
		}

		devices = agent.retrieveDevices(DiscoveryAgent.PREKNOWN);  
		if (devices != null && devices.length > 0) {
			for (RemoteDevice d: devices) {
				if (Debug.DEBUG) {
					System.out.println("preknown: " + d.getBluetoothAddress());
				}
				if (d.getBluetoothAddress().equalsIgnoreCase(address)) {
					return d;
				}
			}
		}
		
		List<RemoteDevice> found = find();
		if (found != null && found.size() > 0) {
			for (RemoteDevice d: found) {
				if (Debug.DEBUG) {
					System.out.println("found: " + d.getBluetoothAddress());
				}
				if (d.getBluetoothAddress().equalsIgnoreCase(address)) {
					return d;
				}
			}
		}
		if (Debug.DEBUG) {
			System.out.println("not found " + address);
		}
		return null;
	}

	public static List<RemoteDevice> find() throws Exception{

		final Object inquiry = new Object();

		devices.clear();

		DiscoveryListener listener = new DiscoveryListener() {

			public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
				if (Debug.DEBUG) {
					System.out.println("Device " + btDevice.getBluetoothAddress()
						+ " found");
				}
				devices.add(btDevice);
				try {
					if (Debug.DEBUG) {
						System.out.println("     name "
							+ btDevice.getFriendlyName(false));
					}
				} catch (IOException cantGetDeviceName) {
				}
			}

			public void inquiryCompleted(int discType) {
				if (Debug.DEBUG) {
					System.out.println("Device Inquiry completed!");
				}
				synchronized (inquiry) {
					inquiry.notifyAll();
				}
			}

			public void serviceSearchCompleted(int transID, int respCode) {
			}

			public void servicesDiscovered(int transID,
					ServiceRecord[] servRecord) {
			}
		};

		synchronized (inquiry) {
			boolean started = LocalDevice.getLocalDevice().getDiscoveryAgent()
					.startInquiry(DiscoveryAgent.GIAC, listener);
			if (started) {
				if (Debug.DEBUG) {
					System.out.println("wait for device inquiry to complete...");
				}
				
				inquiry.wait();
				
				if (Debug.DEBUG) {
					System.out.println(devices.size()
						+ " device(s) found");
				}
			}
		}

		return devices;
	}

}
